package com.xuecheng.system.init;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xuecheng.common.enums.StatusAnnotation;
import com.xuecheng.common.enums.StatusEnum;
import com.xuecheng.system.entity.Dictionary;
import com.xuecheng.system.service.DictionaryService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 *     应用启动时将系统常量信息(枚举)初始化到数据库的数据字典表中--异步服务类
 * </p>
 * 应用启动时将系统常量信息(枚举)初始化到数据库的数据字典表中,本类主要是程序启动时加载执行,考虑不影响主程序的启动,采用Spring的异步方式进行执行
 * @Description: 应用启动时将系统常量信息(枚举)初始化到数据库的数据字典表中,本类主要是程序启动时加载执行
 * @Author: Flippy
 */
@Service
public class StatusContentTaskService {

    @Autowired
    private SanClassResourceLoader<StatusEnum> resourceLoader;

    @Autowired
    private DictionaryService dictionaryService;

    @Async
    @Transactional
    public void loadContent2DataSource() {

        //1.加载指定包下的StatueEnum子类Class对象
        List<Class<StatusEnum>> statusEnums =
                resourceLoader.loadClassesByPackageName("com.xuecheng.common.enums", StatusEnum.class);

        //2.获得Class对象中的属性和自定义注解中的值
        List<Dictionary> dictionarys = getDictionarysByStatusEnum(statusEnums);


        //3.判断是否获得数据字典信息
        if (dictionarys.size() > 0) {

            //3.1 循环遍历获得的Dictionary信息
            for (Dictionary dictionary : dictionarys) {


                // 3.2 根据code和进行查找是否信息存在
                LambdaQueryWrapper<Dictionary> queryWrapper = new LambdaQueryWrapper();

                queryWrapper.eq(Dictionary::getCode, dictionary.getCode());

                // 3.3 获得数据的数据字典在信息
                Dictionary one = dictionaryService.getOne(queryWrapper);

                // 3.4 如果为空则则直接添加
                if (ObjectUtils.isEmpty(one)) {

                    dictionaryService.save(dictionary);

                } else {

                    // 3.5 如果存在进行修改操作
                    dictionary.setId(one.getId());

                    dictionaryService.updateById(dictionary);

                }


            }

        }


    }


    /**
     * 根据StatusEnums的子类Class信息生成数据字典信息
     * @param statusEnums List<Class<StatusEnum>> StatusEnums的子类Class集合信息
     * @return List<Dictionary>
     */
    private List<Dictionary> getDictionarysByStatusEnum(List<Class<StatusEnum>> statusEnums) {

        //0.构建数据字典结果集合信息
        List<Dictionary> dictionaries = new ArrayList<>();

        //1.循环遍历StatusEnums的子类Class集合
        for (Class statusEnum : statusEnums) {

            //2.判断是否有数据字典自定义注解标识
            StatusAnnotation annotation = (StatusAnnotation) statusEnum.getAnnotation(StatusAnnotation.class);

            //3.如果有获得其中的注解信息
            if (!(ObjectUtils.isEmpty(annotation))) {

                //3.1 获得自定义注解中的code值作为字典的code的值
                String code = annotation.code();

                //3.2 获得自定义注解中的name值作为字典的name的值
                String name = annotation.name();

                //3.3 获得枚举的多例信息
                StatusEnum[] enumConstants = (StatusEnum[]) statusEnum.getEnumConstants();

                //3.4 构建FastJson的Config类,让其可以将枚举转为Json字符串
                SerializeConfig config = new SerializeConfig();
                config.configEnumAsJavaBean((Class<? extends Enum>) statusEnum);

                //3.5 将枚举中的多例转为Json信息
                String jsonString = JSON.toJSONString(enumConstants, config);

                //3.6 创建数据字典实体类并设置值
                Dictionary dictionary = new Dictionary();
                dictionary.setCode(StringUtils.defaultIfBlank(code, null));
                dictionary.setName(name);
                dictionary.setItemValues(jsonString);

                //3.7 将数据字典实体类放入结果集合中
                dictionaries.add(dictionary);

            }

        }

        //4.返回结果集合
        return dictionaries;
    }


}